{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 卷积与MNIST\n",
    "\n",
    "在这节课中，我们学习了如何使用torchvision加载图像库，如何构建一个简单的卷积神经网络，并了解如何训练这个卷积神经网络\n",
    "之后，我们还学会了如何对训练好的卷积网络进行分析"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入所需要的包，请import torch.optim as optim\n",
    "import torch.nn.functional as F\n",
    "\n",
    "import torchvision.datasets as dsets\n",
    "import torchvision.transforms as transforms\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一、加载数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. 首先，我们需要学习PyTorch自带的数据加载器，包括dataset，sampler，以及data loader这三个对象组成的套件。\n",
    "2. 当数据集很小，格式比较规则的时候，数据加载三套件的优势并不明显。但是当数据格式比较特殊，以及数据规模很大（内存无法同时加载所有数据）\n",
    "的时候，特别是，我们需要用不同的处理器来加载数据的时候，三套件的威力就会显现出来了。它会将数据加载、分布的任务自动完成。\n",
    "3. 在使用的时候，我们用dataset来装载数据集，用sampler来采样数据集。而对数据集的迭代、循环则主要通过data_loader来完成。\n",
    "4. 创建一个data_loader就需要一个dataset和一个datasampler，它基本实现的就是利用sampler自动从dataset种采样\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz\n",
      "Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz\n",
      "Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz\n",
      "Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz\n",
      "Processing...\n",
      "Done!\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# 定义超参数 \n",
    "image_size = 28  #图像的总尺寸28*28\n",
    "num_classes = 10  #标签的种类数\n",
    "num_epochs = 20  #训练的总循环周期\n",
    "batch_size = 64  #一个撮（批次）的大小，64张图片\n",
    "\n",
    "# 加载MINIST数据，如果没有下载过，就会在当前路径下新建/data子目录，并把文件存放其中\n",
    "# MNIST数据是属于torchvision包自带的数据，所以可以直接调用。\n",
    "# 在调用自己的数据的时候，我们可以用torchvision.datasets.ImageFolder或者torch.utils.data.TensorDataset来加载\n",
    "train_dataset = dsets.MNIST(root='./data',  #文件存放路径\n",
    "                            train=True,   #提取训练集\n",
    "                            transform=transforms.ToTensor(),  #将图像转化为Tensor，在加载数据的时候，就可以对图像做预处理\n",
    "                            download=True) #当找不到文件的时候，自动下载\n",
    "\n",
    "# 加载测试数据集\n",
    "test_dataset = dsets.MNIST(root='./data', \n",
    "                           train=False, \n",
    "                           transform=transforms.ToTensor())\n",
    "\n",
    "# 训练数据集的加载器，自动将数据分割成batch，顺序随机打乱\n",
    "train_loader = torch.utils.data.DataLoader(dataset=train_dataset, \n",
    "                                           batch_size=batch_size, \n",
    "                                           shuffle=True)\n",
    "\n",
    "'''我们希望将测试数据分成两部分，一部分作为校验数据，一部分作为测试数据。\n",
    "校验数据用于检测模型是否过拟合，并调整参数，测试数据检验整个模型的工作'''\n",
    "\n",
    "\n",
    "# 首先，我们定义下标数组indices，它相当于对所有test_dataset中数据的编码\n",
    "# 然后定义下标indices_val来表示校验集数据的那些下标，indices_test表示测试集的下标\n",
    "indices = range(len(test_dataset))\n",
    "indices_val = indices[:5000]\n",
    "indices_test = indices[5000:]\n",
    "\n",
    "# 根据这些下标，构造两个数据集的SubsetRandomSampler采样器，它会对下标进行采样\n",
    "sampler_val = torch.utils.data.sampler.SubsetRandomSampler(indices_val)\n",
    "sampler_test = torch.utils.data.sampler.SubsetRandomSampler(indices_test)\n",
    "\n",
    "# 根据两个采样器来定义加载器，注意将sampler_val和sampler_test分别赋值给了validation_loader和test_loader\n",
    "validation_loader = torch.utils.data.DataLoader(dataset =test_dataset,\n",
    "                                                batch_size = batch_size,\n",
    "                                                sampler = sampler_val\n",
    "                                               )\n",
    "test_loader = torch.utils.data.DataLoader(dataset=test_dataset, \n",
    "                                          batch_size=batch_size, \n",
    "                                          sampler = sampler_test\n",
    "                                         )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "标签是： 5\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f94106a7f98>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#随便从数据集中读入一张图片，并绘制出来\n",
    "idx = 100\n",
    "\n",
    "#dataset支持下标索引，其中提取出来的每一个元素为features，target格式，即属性和标签。[0]表示索引features\n",
    "muteimg = train_dataset[idx][0].numpy()\n",
    "#由于一般的图像包含rgb三个通道，而MINST数据集的图像都是灰度的，只有一个通道。因此，我们忽略通道，把图像看作一个灰度矩阵。\n",
    "#用imshow画图，会将灰度矩阵自动展现为彩色，不同灰度对应不同颜色：从黄到紫\n",
    "\n",
    "plt.imshow(muteimg[0,...])\n",
    "print('标签是：',train_dataset[idx][1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 二、基本的卷积神经网络"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1 构建网络"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注：在这里，我们将主要调用PyTorch强大的nn.Module这个类来构建卷积神经网络。我们分成如下这几个步骤：\n",
    "\n",
    "1. 首先，我们构造ConvNet类，它是对类nn.Module的继承（即nn.Module是父类，ConvNet为子类。如果这些概念不熟悉，请参考面向对象编程）\n",
    "2. 然后，我们复写__init__，以及forward这两个函数。第一个为构造函数，每当类ConvNet被具体化一个实例的时候，就会调用，forward则是\n",
    "在运行神经网络正向的时候会被自动调用\n",
    "3. 自定义自己的方法\n",
    "\n",
    "另一需要理解的是，ConvNet其实也是一个大容器，它里面有Conv2d，MaxPool2d等组件\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "#定义卷积神经网络：4和8为人为指定的两个卷积层的厚度（feature map的数量）\n",
    "depth = [4, 8]\n",
    "class ConvNet(nn.Module):\n",
    "    def __init__(self):\n",
    "        # 该函数在创建一个ConvNet对象的时候，即调用如下语句：net=ConvNet()，就会被调用\n",
    "        # 首先调用父类相应的构造函数\n",
    "        super(ConvNet, self).__init__()\n",
    "        \n",
    "        # 其次构造ConvNet需要用到的各个神经模块。\n",
    "        '''注意，定义组件并没有真正搭建这些组件，只是把基本建筑砖块先找好'''\n",
    "        self.conv1 = nn.Conv2d(1, 4, 5, padding = 2) #定义一个卷积层，输入通道为1，输出通道为4，窗口大小为5，padding为2\n",
    "        self.pool = nn.MaxPool2d(2, 2) #定义一个Pooling层，一个窗口为2*2的pooling运算\n",
    "        self.conv2 = nn.Conv2d(depth[0], depth[1], 5, padding = 2) #第二层卷积，输入通道为depth[0], \n",
    "                                                                   #输出通道为depth[1]，窗口为5，padding为2\n",
    "        self.fc1 = nn.Linear(image_size // 4 * image_size // 4 * depth[1] , 512) \n",
    "                                                            #一个线性连接层，输入尺寸为最后一层立方体的平铺，输出层512个节点\n",
    "        self.fc2 = nn.Linear(512, num_classes) #最后一层线性分类单元，输入为512，输出为要做分类的类别数\n",
    "\n",
    "    def forward(self, x):\n",
    "        #该函数完成神经网络真正的前向运算，我们会在这里把各个组件进行实际的拼装\n",
    "        #x的尺寸：(batch_size, image_channels, image_width, image_height)\n",
    "        x = F.relu(self.conv1(x))  #第一层卷积，激活函数用ReLu，为了防止过拟合\n",
    "        #x的尺寸：(batch_size, num_filters, image_width, image_height)\n",
    "        x = self.pool(x) #第二层pooling，将图片变小\n",
    "        #x的尺寸：(batch_size, depth[0], image_width/2, image_height/2)\n",
    "        x = F.relu(self.conv2(x)) #第三层又是卷积，窗口为5，输入输出通道分别为depth[0]=4, depth[1]=8\n",
    "        #x的尺寸：(batch_size, depth[1], image_width/2, image_height/2)\n",
    "        x = self.pool(x) #第四层pooling，将图片缩小到原大小的1/4\n",
    "        #x的尺寸：(batch_size, depth[1], image_width/4, image_height/4)\n",
    "        \n",
    "        # 将立体的特征图Tensor，压成一个一维的向量\n",
    "        # view这个函数可以将一个tensor按指定的方式重新排布。\n",
    "        # 下面这个命令就是要让x按照batch_size * (image_size//4)^2*depth[1]的方式来排布向量\n",
    "        x = x.view(-1, image_size // 4 * image_size // 4 * depth[1])\n",
    "        #x的尺寸：(batch_size, depth[1]*image_width/4*image_height/4)\n",
    "        \n",
    "        x = F.relu(self.fc1(x)) #第五层为全链接，ReLu激活函数\n",
    "        #x的尺寸：(batch_size, 512)\n",
    "\n",
    "        x = F.dropout(x, training=self.training) #以默认为0.5的概率对这一层进行dropout操作，为了防止过拟合\n",
    "        x = self.fc2(x) #全链接\n",
    "        #x的尺寸：(batch_size, num_classes)\n",
    "        \n",
    "        x = F.log_softmax(x, dim = 0) #输出层为log_softmax，即概率对数值log(p(x))。采用log_softmax可以使得后面的交叉熵计算更快\n",
    "        return x\n",
    "    \n",
    "    def retrieve_features(self, x):\n",
    "        #该函数专门用于提取卷积神经网络的特征图的功能，返回feature_map1, feature_map2为前两层卷积层的特征图\n",
    "        feature_map1 = F.relu(self.conv1(x)) #完成第一层卷积\n",
    "        x = self.pool(feature_map1)  # 完成第一层pooling\n",
    "        feature_map2 = F.relu(self.conv2(x)) #第二层卷积，两层特征图都存储到了feature_map1, feature_map2中\n",
    "        return (feature_map1, feature_map2)\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 训练这个卷积神经网络"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def rightness(predictions, labels):\n",
    "    \"\"\"计算预测错误率的函数，其中predictions是模型给出的一组预测结果，batch_size行num_classes列的矩阵，labels是数据之中的正确答案\"\"\"\n",
    "    pred = torch.max(predictions.data, 1)[1] # 对于任意一行（一个样本）的输出值的第1个维度，求最大，得到每一行的最大元素的下标\n",
    "    rights = pred.eq(labels.data.view_as(pred)).sum() #将下标与labels中包含的类别进行比较，并累计得到比较正确的数量\n",
    "    return rights, len(labels) #返回正确的数量和这一次一共比较了多少元素\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练周期: 0 [0/60000 (0%)]\tLoss: 2.302145\t训练正确率: 6.25%\t校验正确率: 7.50%\n",
      "训练周期: 0 [6400/60000 (11%)]\tLoss: 2.299296\t训练正确率: 10.95%\t校验正确率: 31.90%\n",
      "训练周期: 0 [12800/60000 (21%)]\tLoss: 2.286275\t训练正确率: 14.92%\t校验正确率: 50.36%\n",
      "训练周期: 0 [19200/60000 (32%)]\tLoss: 2.272822\t训练正确率: 18.75%\t校验正确率: 57.58%\n",
      "训练周期: 0 [25600/60000 (43%)]\tLoss: 2.194221\t训练正确率: 22.89%\t校验正确率: 58.28%\n",
      "训练周期: 0 [32000/60000 (53%)]\tLoss: 1.780113\t训练正确率: 27.33%\t校验正确率: 62.16%\n",
      "训练周期: 0 [38400/60000 (64%)]\tLoss: 1.075289\t训练正确率: 32.50%\t校验正确率: 73.34%\n",
      "训练周期: 0 [44800/60000 (75%)]\tLoss: 0.747169\t训练正确率: 37.80%\t校验正确率: 78.48%\n",
      "训练周期: 0 [51200/60000 (85%)]\tLoss: 0.542904\t训练正确率: 42.50%\t校验正确率: 80.84%\n",
      "训练周期: 0 [57600/60000 (96%)]\tLoss: 0.716426\t训练正确率: 46.50%\t校验正确率: 82.94%\n",
      "训练周期: 1 [0/60000 (0%)]\tLoss: 0.617506\t训练正确率: 76.56%\t校验正确率: 84.22%\n",
      "训练周期: 1 [6400/60000 (11%)]\tLoss: 0.443977\t训练正确率: 80.91%\t校验正确率: 84.76%\n",
      "训练周期: 1 [12800/60000 (21%)]\tLoss: 0.503194\t训练正确率: 81.88%\t校验正确率: 85.10%\n",
      "训练周期: 1 [19200/60000 (32%)]\tLoss: 0.470492\t训练正确率: 82.59%\t校验正确率: 87.12%\n",
      "训练周期: 1 [25600/60000 (43%)]\tLoss: 0.252122\t训练正确率: 83.35%\t校验正确率: 87.68%\n",
      "训练周期: 1 [32000/60000 (53%)]\tLoss: 0.554362\t训练正确率: 83.75%\t校验正确率: 87.94%\n",
      "训练周期: 1 [38400/60000 (64%)]\tLoss: 0.324944\t训练正确率: 84.26%\t校验正确率: 88.70%\n",
      "训练周期: 1 [44800/60000 (75%)]\tLoss: 0.351852\t训练正确率: 84.67%\t校验正确率: 89.20%\n",
      "训练周期: 1 [51200/60000 (85%)]\tLoss: 0.702934\t训练正确率: 85.13%\t校验正确率: 90.28%\n",
      "训练周期: 1 [57600/60000 (96%)]\tLoss: 0.208116\t训练正确率: 85.47%\t校验正确率: 90.40%\n",
      "训练周期: 2 [0/60000 (0%)]\tLoss: 0.385950\t训练正确率: 87.50%\t校验正确率: 90.20%\n",
      "训练周期: 2 [6400/60000 (11%)]\tLoss: 0.274087\t训练正确率: 89.63%\t校验正确率: 91.24%\n",
      "训练周期: 2 [12800/60000 (21%)]\tLoss: 0.131810\t训练正确率: 90.04%\t校验正确率: 91.38%\n",
      "训练周期: 2 [19200/60000 (32%)]\tLoss: 0.339918\t训练正确率: 90.12%\t校验正确率: 91.60%\n",
      "训练周期: 2 [25600/60000 (43%)]\tLoss: 0.352621\t训练正确率: 90.24%\t校验正确率: 92.12%\n",
      "训练周期: 2 [32000/60000 (53%)]\tLoss: 0.284093\t训练正确率: 90.46%\t校验正确率: 91.84%\n",
      "训练周期: 2 [38400/60000 (64%)]\tLoss: 0.383984\t训练正确率: 90.60%\t校验正确率: 92.40%\n",
      "训练周期: 2 [44800/60000 (75%)]\tLoss: 0.302222\t训练正确率: 90.72%\t校验正确率: 92.78%\n",
      "训练周期: 2 [51200/60000 (85%)]\tLoss: 0.137342\t训练正确率: 90.78%\t校验正确率: 92.88%\n",
      "训练周期: 2 [57600/60000 (96%)]\tLoss: 0.125910\t训练正确率: 91.03%\t校验正确率: 92.94%\n",
      "训练周期: 3 [0/60000 (0%)]\tLoss: 0.194424\t训练正确率: 96.88%\t校验正确率: 92.96%\n",
      "训练周期: 3 [6400/60000 (11%)]\tLoss: 0.239300\t训练正确率: 93.07%\t校验正确率: 93.24%\n",
      "训练周期: 3 [12800/60000 (21%)]\tLoss: 0.225909\t训练正确率: 92.77%\t校验正确率: 93.54%\n",
      "训练周期: 3 [19200/60000 (32%)]\tLoss: 0.505585\t训练正确率: 92.70%\t校验正确率: 94.00%\n",
      "训练周期: 3 [25600/60000 (43%)]\tLoss: 0.368349\t训练正确率: 92.83%\t校验正确率: 93.86%\n",
      "训练周期: 3 [32000/60000 (53%)]\tLoss: 0.252111\t训练正确率: 92.90%\t校验正确率: 94.46%\n",
      "训练周期: 3 [38400/60000 (64%)]\tLoss: 0.171060\t训练正确率: 92.89%\t校验正确率: 93.80%\n",
      "训练周期: 3 [44800/60000 (75%)]\tLoss: 0.117067\t训练正确率: 92.98%\t校验正确率: 94.10%\n",
      "训练周期: 3 [51200/60000 (85%)]\tLoss: 0.265572\t训练正确率: 93.06%\t校验正确率: 94.22%\n",
      "训练周期: 3 [57600/60000 (96%)]\tLoss: 0.232918\t训练正确率: 93.15%\t校验正确率: 94.64%\n",
      "训练周期: 4 [0/60000 (0%)]\tLoss: 0.274357\t训练正确率: 92.19%\t校验正确率: 94.74%\n",
      "训练周期: 4 [6400/60000 (11%)]\tLoss: 0.163022\t训练正确率: 94.20%\t校验正确率: 94.84%\n",
      "训练周期: 4 [12800/60000 (21%)]\tLoss: 0.269150\t训练正确率: 93.90%\t校验正确率: 94.58%\n",
      "训练周期: 4 [19200/60000 (32%)]\tLoss: 0.140413\t训练正确率: 94.06%\t校验正确率: 94.96%\n",
      "训练周期: 4 [25600/60000 (43%)]\tLoss: 0.194286\t训练正确率: 94.16%\t校验正确率: 95.18%\n",
      "训练周期: 4 [32000/60000 (53%)]\tLoss: 0.209834\t训练正确率: 94.22%\t校验正确率: 95.30%\n",
      "训练周期: 4 [38400/60000 (64%)]\tLoss: 0.278818\t训练正确率: 94.31%\t校验正确率: 95.28%\n",
      "训练周期: 4 [44800/60000 (75%)]\tLoss: 0.160946\t训练正确率: 94.31%\t校验正确率: 94.90%\n",
      "训练周期: 4 [51200/60000 (85%)]\tLoss: 0.090700\t训练正确率: 94.37%\t校验正确率: 95.30%\n",
      "训练周期: 4 [57600/60000 (96%)]\tLoss: 0.057870\t训练正确率: 94.40%\t校验正确率: 95.10%\n",
      "训练周期: 5 [0/60000 (0%)]\tLoss: 0.068759\t训练正确率: 100.00%\t校验正确率: 95.28%\n",
      "训练周期: 5 [6400/60000 (11%)]\tLoss: 0.308135\t训练正确率: 95.41%\t校验正确率: 95.48%\n",
      "训练周期: 5 [12800/60000 (21%)]\tLoss: 0.152924\t训练正确率: 95.36%\t校验正确率: 95.54%\n",
      "训练周期: 5 [19200/60000 (32%)]\tLoss: 0.325374\t训练正确率: 95.18%\t校验正确率: 95.50%\n",
      "训练周期: 5 [25600/60000 (43%)]\tLoss: 0.079676\t训练正确率: 95.17%\t校验正确率: 95.82%\n",
      "训练周期: 5 [32000/60000 (53%)]\tLoss: 0.076872\t训练正确率: 95.12%\t校验正确率: 95.66%\n",
      "训练周期: 5 [38400/60000 (64%)]\tLoss: 0.201080\t训练正确率: 95.16%\t校验正确率: 95.86%\n",
      "训练周期: 5 [44800/60000 (75%)]\tLoss: 0.204832\t训练正确率: 95.21%\t校验正确率: 95.78%\n",
      "训练周期: 5 [51200/60000 (85%)]\tLoss: 0.222559\t训练正确率: 95.24%\t校验正确率: 95.68%\n",
      "训练周期: 5 [57600/60000 (96%)]\tLoss: 0.092276\t训练正确率: 95.27%\t校验正确率: 95.92%\n",
      "训练周期: 6 [0/60000 (0%)]\tLoss: 0.171707\t训练正确率: 93.75%\t校验正确率: 95.80%\n",
      "训练周期: 6 [6400/60000 (11%)]\tLoss: 0.036139\t训练正确率: 95.96%\t校验正确率: 95.68%\n",
      "训练周期: 6 [12800/60000 (21%)]\tLoss: 0.059131\t训练正确率: 95.62%\t校验正确率: 95.80%\n",
      "训练周期: 6 [19200/60000 (32%)]\tLoss: 0.076068\t训练正确率: 95.54%\t校验正确率: 96.02%\n",
      "训练周期: 6 [25600/60000 (43%)]\tLoss: 0.114420\t训练正确率: 95.54%\t校验正确率: 96.08%\n",
      "训练周期: 6 [32000/60000 (53%)]\tLoss: 0.466677\t训练正确率: 95.57%\t校验正确率: 96.30%\n",
      "训练周期: 6 [38400/60000 (64%)]\tLoss: 0.095669\t训练正确率: 95.59%\t校验正确率: 96.26%\n",
      "训练周期: 6 [44800/60000 (75%)]\tLoss: 0.172048\t训练正确率: 95.59%\t校验正确率: 96.18%\n",
      "训练周期: 6 [51200/60000 (85%)]\tLoss: 0.064371\t训练正确率: 95.66%\t校验正确率: 96.34%\n",
      "训练周期: 6 [57600/60000 (96%)]\tLoss: 0.048758\t训练正确率: 95.71%\t校验正确率: 96.10%\n",
      "训练周期: 7 [0/60000 (0%)]\tLoss: 0.228669\t训练正确率: 90.62%\t校验正确率: 96.22%\n",
      "训练周期: 7 [6400/60000 (11%)]\tLoss: 0.187649\t训练正确率: 95.95%\t校验正确率: 96.40%\n",
      "训练周期: 7 [12800/60000 (21%)]\tLoss: 0.081149\t训练正确率: 96.17%\t校验正确率: 96.36%\n",
      "训练周期: 7 [19200/60000 (32%)]\tLoss: 0.089059\t训练正确率: 96.18%\t校验正确率: 96.24%\n",
      "训练周期: 7 [25600/60000 (43%)]\tLoss: 0.197613\t训练正确率: 96.05%\t校验正确率: 96.78%\n",
      "训练周期: 7 [32000/60000 (53%)]\tLoss: 0.112545\t训练正确率: 96.06%\t校验正确率: 96.28%\n",
      "训练周期: 7 [38400/60000 (64%)]\tLoss: 0.133209\t训练正确率: 96.13%\t校验正确率: 96.34%\n",
      "训练周期: 7 [44800/60000 (75%)]\tLoss: 0.117675\t训练正确率: 96.07%\t校验正确率: 96.50%\n",
      "训练周期: 7 [51200/60000 (85%)]\tLoss: 0.156509\t训练正确率: 96.05%\t校验正确率: 96.52%\n",
      "训练周期: 7 [57600/60000 (96%)]\tLoss: 0.110958\t训练正确率: 96.07%\t校验正确率: 96.68%\n",
      "训练周期: 8 [0/60000 (0%)]\tLoss: 0.077264\t训练正确率: 98.44%\t校验正确率: 96.36%\n",
      "训练周期: 8 [6400/60000 (11%)]\tLoss: 0.155207\t训练正确率: 96.26%\t校验正确率: 96.60%\n",
      "训练周期: 8 [12800/60000 (21%)]\tLoss: 0.142497\t训练正确率: 96.16%\t校验正确率: 96.50%\n",
      "训练周期: 8 [19200/60000 (32%)]\tLoss: 0.344341\t训练正确率: 96.19%\t校验正确率: 96.54%\n",
      "训练周期: 8 [25600/60000 (43%)]\tLoss: 0.110069\t训练正确率: 96.26%\t校验正确率: 96.56%\n",
      "训练周期: 8 [32000/60000 (53%)]\tLoss: 0.078099\t训练正确率: 96.36%\t校验正确率: 96.72%\n",
      "训练周期: 8 [38400/60000 (64%)]\tLoss: 0.036106\t训练正确率: 96.40%\t校验正确率: 96.78%\n",
      "训练周期: 8 [44800/60000 (75%)]\tLoss: 0.097623\t训练正确率: 96.42%\t校验正确率: 96.78%\n",
      "训练周期: 8 [51200/60000 (85%)]\tLoss: 0.202770\t训练正确率: 96.41%\t校验正确率: 96.86%\n",
      "训练周期: 8 [57600/60000 (96%)]\tLoss: 0.090401\t训练正确率: 96.40%\t校验正确率: 97.04%\n",
      "训练周期: 9 [0/60000 (0%)]\tLoss: 0.040943\t训练正确率: 98.44%\t校验正确率: 96.92%\n",
      "训练周期: 9 [6400/60000 (11%)]\tLoss: 0.173068\t训练正确率: 96.58%\t校验正确率: 96.44%\n",
      "训练周期: 9 [12800/60000 (21%)]\tLoss: 0.046943\t训练正确率: 96.78%\t校验正确率: 96.64%\n",
      "训练周期: 9 [19200/60000 (32%)]\tLoss: 0.071374\t训练正确率: 96.67%\t校验正确率: 96.98%\n",
      "训练周期: 9 [25600/60000 (43%)]\tLoss: 0.092340\t训练正确率: 96.62%\t校验正确率: 96.92%\n",
      "训练周期: 9 [32000/60000 (53%)]\tLoss: 0.045087\t训练正确率: 96.61%\t校验正确率: 96.68%\n",
      "训练周期: 9 [38400/60000 (64%)]\tLoss: 0.243472\t训练正确率: 96.66%\t校验正确率: 96.86%\n",
      "训练周期: 9 [44800/60000 (75%)]\tLoss: 0.111831\t训练正确率: 96.69%\t校验正确率: 96.94%\n",
      "训练周期: 9 [51200/60000 (85%)]\tLoss: 0.121630\t训练正确率: 96.74%\t校验正确率: 96.90%\n",
      "训练周期: 9 [57600/60000 (96%)]\tLoss: 0.046509\t训练正确率: 96.77%\t校验正确率: 97.24%\n",
      "训练周期: 10 [0/60000 (0%)]\tLoss: 0.069827\t训练正确率: 100.00%\t校验正确率: 97.08%\n",
      "训练周期: 10 [6400/60000 (11%)]\tLoss: 0.157163\t训练正确率: 96.69%\t校验正确率: 97.08%\n",
      "训练周期: 10 [12800/60000 (21%)]\tLoss: 0.128678\t训练正确率: 96.91%\t校验正确率: 97.06%\n",
      "训练周期: 10 [19200/60000 (32%)]\tLoss: 0.240922\t训练正确率: 96.83%\t校验正确率: 97.06%\n",
      "训练周期: 10 [25600/60000 (43%)]\tLoss: 0.075379\t训练正确率: 96.80%\t校验正确率: 96.86%\n",
      "训练周期: 10 [32000/60000 (53%)]\tLoss: 0.033976\t训练正确率: 96.80%\t校验正确率: 97.26%\n",
      "训练周期: 10 [38400/60000 (64%)]\tLoss: 0.057407\t训练正确率: 96.79%\t校验正确率: 97.18%\n",
      "训练周期: 10 [44800/60000 (75%)]\tLoss: 0.141837\t训练正确率: 96.83%\t校验正确率: 97.14%\n",
      "训练周期: 10 [51200/60000 (85%)]\tLoss: 0.034691\t训练正确率: 96.81%\t校验正确率: 97.02%\n",
      "训练周期: 10 [57600/60000 (96%)]\tLoss: 0.042125\t训练正确率: 96.84%\t校验正确率: 96.82%\n",
      "训练周期: 11 [0/60000 (0%)]\tLoss: 0.074475\t训练正确率: 96.88%\t校验正确率: 97.08%\n",
      "训练周期: 11 [6400/60000 (11%)]\tLoss: 0.079011\t训练正确率: 97.39%\t校验正确率: 96.84%\n",
      "训练周期: 11 [12800/60000 (21%)]\tLoss: 0.153749\t训练正确率: 97.46%\t校验正确率: 97.10%\n",
      "训练周期: 11 [19200/60000 (32%)]\tLoss: 0.030239\t训练正确率: 97.24%\t校验正确率: 97.00%\n",
      "训练周期: 11 [25600/60000 (43%)]\tLoss: 0.258549\t训练正确率: 97.18%\t校验正确率: 96.90%\n",
      "训练周期: 11 [32000/60000 (53%)]\tLoss: 0.093703\t训练正确率: 97.13%\t校验正确率: 96.90%\n",
      "训练周期: 11 [38400/60000 (64%)]\tLoss: 0.041337\t训练正确率: 97.15%\t校验正确率: 97.02%\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练周期: 11 [44800/60000 (75%)]\tLoss: 0.037554\t训练正确率: 97.16%\t校验正确率: 97.16%\n",
      "训练周期: 11 [51200/60000 (85%)]\tLoss: 0.042862\t训练正确率: 97.14%\t校验正确率: 97.32%\n",
      "训练周期: 11 [57600/60000 (96%)]\tLoss: 0.072454\t训练正确率: 97.15%\t校验正确率: 97.30%\n",
      "训练周期: 12 [0/60000 (0%)]\tLoss: 0.191360\t训练正确率: 93.75%\t校验正确率: 97.38%\n",
      "训练周期: 12 [6400/60000 (11%)]\tLoss: 0.034929\t训练正确率: 97.39%\t校验正确率: 97.00%\n",
      "训练周期: 12 [12800/60000 (21%)]\tLoss: 0.054707\t训练正确率: 97.31%\t校验正确率: 97.44%\n",
      "训练周期: 12 [19200/60000 (32%)]\tLoss: 0.098524\t训练正确率: 97.23%\t校验正确率: 97.36%\n",
      "训练周期: 12 [25600/60000 (43%)]\tLoss: 0.070930\t训练正确率: 97.22%\t校验正确率: 96.96%\n",
      "训练周期: 12 [32000/60000 (53%)]\tLoss: 0.089388\t训练正确率: 97.22%\t校验正确率: 97.32%\n",
      "训练周期: 12 [38400/60000 (64%)]\tLoss: 0.058184\t训练正确率: 97.20%\t校验正确率: 97.28%\n",
      "训练周期: 12 [44800/60000 (75%)]\tLoss: 0.063206\t训练正确率: 97.21%\t校验正确率: 97.28%\n",
      "训练周期: 12 [51200/60000 (85%)]\tLoss: 0.029269\t训练正确率: 97.21%\t校验正确率: 97.40%\n",
      "训练周期: 12 [57600/60000 (96%)]\tLoss: 0.048844\t训练正确率: 97.25%\t校验正确率: 97.56%\n",
      "训练周期: 13 [0/60000 (0%)]\tLoss: 0.036451\t训练正确率: 98.44%\t校验正确率: 97.74%\n",
      "训练周期: 13 [6400/60000 (11%)]\tLoss: 0.022755\t训练正确率: 96.97%\t校验正确率: 97.12%\n",
      "训练周期: 13 [12800/60000 (21%)]\tLoss: 0.086591\t训练正确率: 97.26%\t校验正确率: 97.78%\n",
      "训练周期: 13 [19200/60000 (32%)]\tLoss: 0.050491\t训练正确率: 97.18%\t校验正确率: 97.52%\n",
      "训练周期: 13 [25600/60000 (43%)]\tLoss: 0.087999\t训练正确率: 97.23%\t校验正确率: 97.18%\n",
      "训练周期: 13 [32000/60000 (53%)]\tLoss: 0.155590\t训练正确率: 97.30%\t校验正确率: 97.48%\n",
      "训练周期: 13 [38400/60000 (64%)]\tLoss: 0.119250\t训练正确率: 97.30%\t校验正确率: 97.62%\n",
      "训练周期: 13 [44800/60000 (75%)]\tLoss: 0.106772\t训练正确率: 97.28%\t校验正确率: 97.60%\n",
      "训练周期: 13 [51200/60000 (85%)]\tLoss: 0.068709\t训练正确率: 97.29%\t校验正确率: 97.44%\n",
      "训练周期: 13 [57600/60000 (96%)]\tLoss: 0.032764\t训练正确率: 97.31%\t校验正确率: 97.48%\n",
      "训练周期: 14 [0/60000 (0%)]\tLoss: 0.053691\t训练正确率: 98.44%\t校验正确率: 97.60%\n",
      "训练周期: 14 [6400/60000 (11%)]\tLoss: 0.059278\t训练正确率: 97.34%\t校验正确率: 97.34%\n",
      "训练周期: 14 [12800/60000 (21%)]\tLoss: 0.040367\t训练正确率: 97.50%\t校验正确率: 97.56%\n",
      "训练周期: 14 [19200/60000 (32%)]\tLoss: 0.077611\t训练正确率: 97.57%\t校验正确率: 97.36%\n",
      "训练周期: 14 [25600/60000 (43%)]\tLoss: 0.099269\t训练正确率: 97.56%\t校验正确率: 97.52%\n",
      "训练周期: 14 [32000/60000 (53%)]\tLoss: 0.068826\t训练正确率: 97.59%\t校验正确率: 97.50%\n",
      "训练周期: 14 [38400/60000 (64%)]\tLoss: 0.036331\t训练正确率: 97.55%\t校验正确率: 97.40%\n",
      "训练周期: 14 [44800/60000 (75%)]\tLoss: 0.077425\t训练正确率: 97.56%\t校验正确率: 97.44%\n",
      "训练周期: 14 [51200/60000 (85%)]\tLoss: 0.014908\t训练正确率: 97.53%\t校验正确率: 97.52%\n",
      "训练周期: 14 [57600/60000 (96%)]\tLoss: 0.166893\t训练正确率: 97.54%\t校验正确率: 97.88%\n",
      "训练周期: 15 [0/60000 (0%)]\tLoss: 0.033184\t训练正确率: 98.44%\t校验正确率: 97.94%\n",
      "训练周期: 15 [6400/60000 (11%)]\tLoss: 0.027986\t训练正确率: 97.48%\t校验正确率: 97.48%\n",
      "训练周期: 15 [12800/60000 (21%)]\tLoss: 0.074176\t训练正确率: 97.67%\t校验正确率: 97.20%\n",
      "训练周期: 15 [19200/60000 (32%)]\tLoss: 0.024907\t训练正确率: 97.63%\t校验正确率: 97.58%\n",
      "训练周期: 15 [25600/60000 (43%)]\tLoss: 0.103949\t训练正确率: 97.54%\t校验正确率: 97.60%\n",
      "训练周期: 15 [32000/60000 (53%)]\tLoss: 0.010644\t训练正确率: 97.57%\t校验正确率: 97.44%\n",
      "训练周期: 15 [38400/60000 (64%)]\tLoss: 0.056403\t训练正确率: 97.56%\t校验正确率: 97.42%\n",
      "训练周期: 15 [44800/60000 (75%)]\tLoss: 0.077982\t训练正确率: 97.56%\t校验正确率: 97.72%\n",
      "训练周期: 15 [51200/60000 (85%)]\tLoss: 0.090187\t训练正确率: 97.57%\t校验正确率: 97.40%\n",
      "训练周期: 15 [57600/60000 (96%)]\tLoss: 0.069858\t训练正确率: 97.57%\t校验正确率: 97.56%\n",
      "训练周期: 16 [0/60000 (0%)]\tLoss: 0.065481\t训练正确率: 95.31%\t校验正确率: 97.58%\n",
      "训练周期: 16 [6400/60000 (11%)]\tLoss: 0.054930\t训练正确率: 97.25%\t校验正确率: 97.68%\n",
      "训练周期: 16 [12800/60000 (21%)]\tLoss: 0.113579\t训练正确率: 97.55%\t校验正确率: 97.64%\n",
      "训练周期: 16 [19200/60000 (32%)]\tLoss: 0.065311\t训练正确率: 97.56%\t校验正确率: 97.60%\n",
      "训练周期: 16 [25600/60000 (43%)]\tLoss: 0.109788\t训练正确率: 97.61%\t校验正确率: 97.74%\n",
      "训练周期: 16 [32000/60000 (53%)]\tLoss: 0.110342\t训练正确率: 97.60%\t校验正确率: 97.42%\n",
      "训练周期: 16 [38400/60000 (64%)]\tLoss: 0.073865\t训练正确率: 97.60%\t校验正确率: 97.56%\n",
      "训练周期: 16 [44800/60000 (75%)]\tLoss: 0.072468\t训练正确率: 97.61%\t校验正确率: 97.38%\n",
      "训练周期: 16 [51200/60000 (85%)]\tLoss: 0.020997\t训练正确率: 97.63%\t校验正确率: 97.60%\n",
      "训练周期: 16 [57600/60000 (96%)]\tLoss: 0.050090\t训练正确率: 97.67%\t校验正确率: 97.54%\n",
      "训练周期: 17 [0/60000 (0%)]\tLoss: 0.158583\t训练正确率: 92.19%\t校验正确率: 97.66%\n",
      "训练周期: 17 [6400/60000 (11%)]\tLoss: 0.008247\t训练正确率: 97.62%\t校验正确率: 97.74%\n",
      "训练周期: 17 [12800/60000 (21%)]\tLoss: 0.074915\t训练正确率: 97.64%\t校验正确率: 97.56%\n",
      "训练周期: 17 [19200/60000 (32%)]\tLoss: 0.109176\t训练正确率: 97.63%\t校验正确率: 97.58%\n",
      "训练周期: 17 [25600/60000 (43%)]\tLoss: 0.010820\t训练正确率: 97.68%\t校验正确率: 97.52%\n",
      "训练周期: 17 [32000/60000 (53%)]\tLoss: 0.050467\t训练正确率: 97.70%\t校验正确率: 97.86%\n",
      "训练周期: 17 [38400/60000 (64%)]\tLoss: 0.061045\t训练正确率: 97.73%\t校验正确率: 97.68%\n",
      "训练周期: 17 [44800/60000 (75%)]\tLoss: 0.032651\t训练正确率: 97.70%\t校验正确率: 97.78%\n",
      "训练周期: 17 [51200/60000 (85%)]\tLoss: 0.080904\t训练正确率: 97.72%\t校验正确率: 97.60%\n",
      "训练周期: 17 [57600/60000 (96%)]\tLoss: 0.052019\t训练正确率: 97.76%\t校验正确率: 97.66%\n",
      "训练周期: 18 [0/60000 (0%)]\tLoss: 0.078645\t训练正确率: 96.88%\t校验正确率: 97.58%\n",
      "训练周期: 18 [6400/60000 (11%)]\tLoss: 0.027929\t训练正确率: 98.10%\t校验正确率: 97.64%\n",
      "训练周期: 18 [12800/60000 (21%)]\tLoss: 0.028432\t训练正确率: 97.85%\t校验正确率: 97.80%\n",
      "训练周期: 18 [19200/60000 (32%)]\tLoss: 0.051474\t训练正确率: 98.02%\t校验正确率: 97.92%\n",
      "训练周期: 18 [25600/60000 (43%)]\tLoss: 0.072568\t训练正确率: 97.88%\t校验正确率: 97.92%\n",
      "训练周期: 18 [32000/60000 (53%)]\tLoss: 0.077890\t训练正确率: 97.86%\t校验正确率: 97.96%\n",
      "训练周期: 18 [38400/60000 (64%)]\tLoss: 0.031455\t训练正确率: 97.86%\t校验正确率: 97.72%\n",
      "训练周期: 18 [44800/60000 (75%)]\tLoss: 0.010349\t训练正确率: 97.85%\t校验正确率: 97.60%\n",
      "训练周期: 18 [51200/60000 (85%)]\tLoss: 0.066904\t训练正确率: 97.83%\t校验正确率: 97.84%\n",
      "训练周期: 18 [57600/60000 (96%)]\tLoss: 0.081054\t训练正确率: 97.81%\t校验正确率: 97.70%\n",
      "训练周期: 19 [0/60000 (0%)]\tLoss: 0.138328\t训练正确率: 95.31%\t校验正确率: 97.94%\n",
      "训练周期: 19 [6400/60000 (11%)]\tLoss: 0.083752\t训练正确率: 97.71%\t校验正确率: 97.86%\n",
      "训练周期: 19 [12800/60000 (21%)]\tLoss: 0.019239\t训练正确率: 97.72%\t校验正确率: 97.82%\n",
      "训练周期: 19 [19200/60000 (32%)]\tLoss: 0.023147\t训练正确率: 97.77%\t校验正确率: 97.70%\n",
      "训练周期: 19 [25600/60000 (43%)]\tLoss: 0.033405\t训练正确率: 97.77%\t校验正确率: 97.94%\n",
      "训练周期: 19 [32000/60000 (53%)]\tLoss: 0.046236\t训练正确率: 97.80%\t校验正确率: 97.86%\n",
      "训练周期: 19 [38400/60000 (64%)]\tLoss: 0.041573\t训练正确率: 97.84%\t校验正确率: 98.00%\n",
      "训练周期: 19 [44800/60000 (75%)]\tLoss: 0.037896\t训练正确率: 97.85%\t校验正确率: 97.62%\n",
      "训练周期: 19 [51200/60000 (85%)]\tLoss: 0.097624\t训练正确率: 97.89%\t校验正确率: 97.92%\n",
      "训练周期: 19 [57600/60000 (96%)]\tLoss: 0.119237\t训练正确率: 97.91%\t校验正确率: 97.84%\n"
     ]
    }
   ],
   "source": [
    "net = ConvNet() #新建一个卷积神经网络的实例，此时ConvNet的__init__函数就会被自动调用\n",
    "\n",
    "criterion = nn.CrossEntropyLoss() #Loss函数的定义，交叉熵\n",
    "optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) #定义优化器，普通的随机梯度下降算法\n",
    "\n",
    "record = [] #记录准确率等数值的容器\n",
    "weights = [] #每若干步就记录一次卷积核\n",
    "\n",
    "#开始训练循环\n",
    "for epoch in range(num_epochs):\n",
    "    \n",
    "    train_rights = [] #记录训练数据集准确率的容器\n",
    "    \n",
    "    ''' 下面的enumerate是构造一个枚举器的作用。就是我们在对train_loader做循环迭代的时候，enumerate会自动吐出一个数字指示我们循环了几次\n",
    "     这个数字就被记录在了batch_idx之中，它就等于0，1，2，……\n",
    "     train_loader每迭代一次，就会吐出来一对数据data和target，分别对应着一个batch中的手写数字图，以及对应的标签。'''\n",
    "    \n",
    "    for batch_idx, (data, target) in enumerate(train_loader):  #针对容器中的每一个批进行循环\n",
    "#         data为一批图像，target为一批标签\n",
    "        net.train() # 给网络模型做标记，标志说模型正在训练集上训练，\n",
    "                    #这种区分主要是为了打开关闭net的training标志，从而决定是否运行dropout\n",
    "            \n",
    "        output = net(data) #神经网络完成一次前馈的计算过程，得到预测输出output\n",
    "        loss = criterion(output, target) #将output与标签target比较，计算误差\n",
    "        optimizer.zero_grad() #清空梯度\n",
    "        loss.backward() #反向传播\n",
    "        optimizer.step() #一步随机梯度下降算法\n",
    "        right = rightness(output, target) #计算准确率所需数值，返回数值为（正确样例数，总样本数）\n",
    "        train_rights.append(right) #将计算结果装到列表容器train_rights中\n",
    "\n",
    "    \n",
    "        if batch_idx % 100 == 0: #每间隔100个batch执行一次打印等操作\n",
    "            \n",
    "            net.eval() # 给网络模型做标记，标志说模型在训练集上训练\n",
    "            val_rights = [] #记录校验数据集准确率的容器\n",
    "            \n",
    "            '''开始在校验数据集上做循环，计算校验集上面的准确度'''\n",
    "            for (data, target) in validation_loader:\n",
    "                output = net(data) #完成一次前馈计算过程，得到目前训练得到的模型net在校验数据集上的表现\n",
    "                right = rightness(output, target) #计算准确率所需数值，返回正确的数值为（正确样例数，总样本数）\n",
    "                val_rights.append(right)\n",
    "            \n",
    "            # 分别计算在目前已经计算过的测试数据集，以及全部校验集上模型的表现：分类准确率\n",
    "            #train_r为一个二元组，分别记录目前已经经历过的所有训练集中分类正确的数量和该集合中总的样本数，\n",
    "            #train_r[0]/train_r[1]就是训练集的分类准确度，同样，val_r[0]/val_r[1]就是校验集上的分类准确度\n",
    "            train_r = (sum([tup[0] for tup in train_rights]), sum([tup[1] for tup in train_rights]))\n",
    "            #val_r为一个二元组，分别记录校验集中分类正确的数量和该集合中总的样本数\n",
    "            val_r = (sum([tup[0] for tup in val_rights]), sum([tup[1] for tup in val_rights]))\n",
    "            #打印准确率等数值，其中正确率为本训练周期Epoch开始后到目前撮的正确率的平均值\n",
    "            print('训练周期: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}\\t训练正确率: {:.2f}%\\t校验正确率: {:.2f}%'.format(\n",
    "                epoch, batch_idx * batch_size, len(train_loader.dataset),\n",
    "                100. * batch_idx / len(train_loader), loss.data[0], \n",
    "                100. * train_r[0] / train_r[1], \n",
    "                100. * val_r[0] / val_r[1]))\n",
    "            \n",
    "            #将准确率和权重等数值加载到容器中，以方便后续处理\n",
    "            record.append((100 - 100. * train_r[0] / train_r[1], 100 - 100. * val_r[0] / val_r[1]))\n",
    "            \n",
    "            # weights记录了训练周期中所有卷积核的演化过程。net.conv1.weight就提取出了第一层卷积核的权重\n",
    "            # clone的意思就是将weight.data中的数据做一个拷贝放到列表中，否则当weight.data变化的时候，列表中的每一项数值也会联动\n",
    "            '''这里使用clone这个函数很重要'''\n",
    "            weights.append([net.conv1.weight.data.clone(), net.conv1.bias.data.clone(), \n",
    "                            net.conv2.weight.data.clone(), net.conv2.bias.data.clone()])\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0,0.5,'Error rate')"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940c7de1d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#绘制训练过程的误差曲线，校验集和测试集上的错误率。\n",
    "plt.figure(figsize = (10, 7))\n",
    "plt.plot(record) #record记载了每一个打印周期记录的训练和校验数据集上的准确度\n",
    "plt.xlabel('Steps')\n",
    "plt.ylabel('Error rate')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3 在测试集上进行分类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.989"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#在测试集上分批运行，并计算总的正确率\n",
    "net.eval() #标志模型当前为运行阶段\n",
    "vals = [] #记录准确率所用列表\n",
    "\n",
    "#对测试数据集进行循环\n",
    "with torch.no_grad():\n",
    "    for data, target in test_loader:\n",
    "        output = net(data) #将特征数据喂入网络，得到分类的输出\n",
    "        val = rightness(output, target) #获得正确样本数以及总样本数\n",
    "        vals.append(val) #记录结果\n",
    "\n",
    "#计算准确率\n",
    "rights = (sum([tup[0] for tup in vals]), sum([tup[1] for tup in vals]))\n",
    "right_rate = 1.0 * rights[0] / rights[1]\n",
    "right_rate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "标签是： 4\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940c924748>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#随便从测试集中读入一张图片，并检验模型的分类结果，并绘制出来\n",
    "idx = 4\n",
    "muteimg = test_dataset[idx][0].numpy()\n",
    "plt.imshow(muteimg[0,...])\n",
    "print('标签是：',test_dataset[idx][1])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 三、解剖卷积神经网络"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以将训练好的卷积神经网络net进行解剖。我们主要关注一下几个问题：\n",
    "1. 第一层卷积核训练得到了什么；\n",
    "2. 第一层卷积核是如何在训练的过程中随着时间的演化而发生变化\n",
    "3. 在输入特定图像的时候，第一层卷积核所对应的4个featuremap是什么样子\n",
    "4. 第二层卷积核都是什么东西？\n",
    "5. 对于给定输入图像，第二层卷积核所对应的那些featuremaps都是什么样？\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1 第一层卷积核、演化与特征图"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 第一层卷积核"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940c924470>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#提取第一层卷积层的卷积核\n",
    "plt.figure(figsize = (10, 7))\n",
    "for i in range(4):\n",
    "    plt.subplot(1,4,i + 1)\n",
    "    plt.axis('off')\n",
    "    plt.imshow(net.conv1.weight.data.numpy()[i,0,...]) #提取第一层卷积核中的权重值，注意conv1是net的属性\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 滤波器的演化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9409f64c50>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9409ddf278>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9409cc8be0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940c80e400>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940c83bb38>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9405ade048>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f94059c1390>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9405929208>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9405812940>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940577d278>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940565dfd0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9405551198>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f94054b4e10>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f94053a7278>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f94052fbcc0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f94051e3a58>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f94050cfa90>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9405033c88>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9404fcb940>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9404e0f828>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 将记录在容器中的卷积核权重历史演化数据打印出来\n",
    "i = 0\n",
    "for tup in weights:\n",
    "    if i % 10 == 0 :\n",
    "        layer1 = tup[0]\n",
    "        fig = plt.figure(figsize = (10, 7))\n",
    "        for j in range(4):\n",
    "            plt.subplot(1, 4, j + 1)\n",
    "            plt.axis('off')\n",
    "            plt.imshow(layer1.numpy()[j,0,...])\n",
    "    i += 1\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 绘制第一层特征图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9404fc1278>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#调用net的retrieve_features方法可以抽取出喂入当前数据后吐出来的所有特征图（第一个卷积和第二个卷积层）\n",
    "\n",
    "#首先定义读入的图片\n",
    "\n",
    "#它是从test_dataset中提取第idx个批次的第0个图，其次unsqueeze的作用是在最前面添加一维，\n",
    "#目的是为了让这个input_x的tensor是四维的，这样才能输入给net。补充的那一维表示batch。\n",
    "input_x = test_dataset[idx][0].unsqueeze(0) \n",
    "feature_maps = net.retrieve_features(input_x) #feature_maps是有两个元素的列表，分别表示第一层和第二层卷积的所有特征图\n",
    "\n",
    "plt.figure(figsize = (10, 7))\n",
    "\n",
    "#有四个特征图，循环把它们打印出来\n",
    "for i in range(4):\n",
    "    plt.subplot(1,4,i + 1)\n",
    "    plt.axis('off')\n",
    "    plt.imshow(feature_maps[0][0, i,...].data.numpy())\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 绘制第二层卷积核与特征图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940c8ef358>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制第二层的卷积核，每一列对应一个卷积核，一共8个卷积核\n",
    "plt.figure(figsize = (15, 10))\n",
    "for i in range(4):\n",
    "    for j in range(8):\n",
    "        plt.subplot(4, 8, i * 8 + j + 1)\n",
    "        plt.axis('off')\n",
    "        plt.imshow(net.conv2.weight.data.numpy()[j, i,...])\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940479f4e0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制第二层的特征图，一共八个\n",
    "plt.figure(figsize = (10, 7))\n",
    "for i in range(8):\n",
    "    plt.subplot(2,4,i + 1)\n",
    "    plt.axis('off')\n",
    "    plt.imshow(feature_maps[1][0, i,...].data.numpy())\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.3 卷积神经网络的鲁棒性试验\n",
    "\n",
    "该试验设计如下：我们随机挑选一张测试图像，把它往左平移w个单位，然后：\n",
    "1. 考察分类结果是否变化\n",
    "2. 考察两层卷积对应的featuremap们有何变化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " 0\n",
      "[torch.LongTensor of size 1]\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9405a98828>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940c8e4908>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f940c8ef908>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 提取中test_dataset中的第idx个批次的第0个图的第0个通道对应的图像，定义为a。\n",
    "a = test_dataset[idx][0][0]\n",
    "\n",
    "# 平移后的新图像将放到b中。根据a给b赋值。\n",
    "b = torch.zeros(a.size()) #全0的28*28的矩阵\n",
    "w = 3 #平移的长度为3个像素\n",
    "\n",
    "# 对于b中的任意像素i,j，它等于a中的i,j+w这个位置的像素\n",
    "for i in range(a.size()[0]):\n",
    "    for j in range(0, a.size()[1] - w):\n",
    "        b[i, j] = a[i, j + w]\n",
    "\n",
    "# 将b画出来\n",
    "muteimg = b.numpy()\n",
    "plt.axis('off')\n",
    "plt.imshow(muteimg)\n",
    "\n",
    "# 把b喂给神经网络，得到分类结果pred（prediction是预测的每一个类别的概率的对数值），并把结果打印出来\n",
    "prediction = net(b.unsqueeze(0).unsqueeze(0))\n",
    "pred = torch.max(prediction.data, 1)[1]\n",
    "print(pred)\n",
    "\n",
    "#提取b对应的featuremap结果\n",
    "feature_maps = net.retrieve_features(b.unsqueeze(0).unsqueeze(0))\n",
    "\n",
    "plt.figure(figsize = (10, 7))\n",
    "for i in range(4):\n",
    "    plt.subplot(1,4,i + 1)\n",
    "    plt.axis('off')\n",
    "    plt.imshow(feature_maps[0][0, i,...].data.numpy())\n",
    "\n",
    "plt.figure(figsize = (10, 7))\n",
    "for i in range(8):\n",
    "    plt.subplot(2,4,i + 1)\n",
    "    plt.axis('off')\n",
    "\n",
    "    plt.imshow(feature_maps[1][0, i,...].data.numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 附录：不用dataloader版本的卷积神经网络\n",
    "\n",
    "如果不喜欢用PyTorch自带的dataset，dataloader等加载数据，可以用下面的代码来完成卷积神经网络的计算\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "import gzip\n",
    "import os\n",
    "import sys\n",
    "\n",
    "from six.moves import urllib\n",
    "\n",
    "#定义一系列常数\n",
    "SOURCE_URL = 'http://yann.lecun.com/exdb/mnist/' #图像数据如果没下载，可以从这个地址下载\n",
    "WORK_DIRECTORY = 'data' #存储的路径名\n",
    "IMAGE_SIZE = 28 #每张图片的大小尺寸\n",
    "NUM_CHANNELS = 1  #每张图片的通道数\n",
    "PIXEL_DEPTH = 255 #像素的深度0-255\n",
    "NUM_LABELS = 10 #手写数字，一共十种\n",
    "VALIDATION_SIZE = 5000 #校验数据集大小\n",
    "NUM_EPOCHS = 20 # 训练的循环周期\n",
    "BATCH_SIZE = 64 #batch的大小\n",
    "EVAL_FREQUENCY = 100 #每隔100个batch进行一次校验集计算\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "#下载图像文件，如果文件已经存在，那么就不下载。\n",
    "def maybe_download(filename):\n",
    "    \"\"\"Download the data from Yann's website, unless it's already here.\"\"\"\n",
    "    if not os.path.isdir(WORK_DIRECTORY):\n",
    "        os.mkdir(WORK_DIRECTORY)\n",
    "    filepath = os.path.join(WORK_DIRECTORY, filename)\n",
    "    if not os.path.exists(filepath):\n",
    "        filepath, _ = urllib.request.urlretrieve(SOURCE_URL + filename, filepath)\n",
    "        size = os.path.getsize(filepath)\n",
    "        print('Successfully downloaded', filename, size, 'bytes.')\n",
    "    return filepath\n",
    "# Get the data.\n",
    "train_data_filename = maybe_download('train-images-idx3-ubyte.gz')\n",
    "train_labels_filename = maybe_download('train-labels-idx1-ubyte.gz')\n",
    "test_data_filename = maybe_download('t10k-images-idx3-ubyte.gz')\n",
    "test_labels_filename = maybe_download('t10k-labels-idx1-ubyte.gz')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting data/train-images-idx3-ubyte.gz\n",
      "Extracting data/train-labels-idx1-ubyte.gz\n",
      "Extracting data/t10k-images-idx3-ubyte.gz\n",
      "Extracting data/t10k-labels-idx1-ubyte.gz\n"
     ]
    }
   ],
   "source": [
    "def extract_data(filename, num_images):\n",
    "    # filename: 文件存放的路径，num_images: 读入的图片个数\n",
    "    \"\"\"将图像解压缩展开，读入成一个4维的张量： [image index（图像的编码）, y（纵坐标）, x（横坐标）, channels（通道）].\n",
    "    我们将数组中的数值范围从原来的[0, 255]降低到了[-0.5, 0.5]范围内\n",
    "    \"\"\"\n",
    "    print('Extracting', filename)\n",
    "    with gzip.open(filename) as bytestream:\n",
    "        bytestream.read(16)\n",
    "        buf = bytestream.read(IMAGE_SIZE * IMAGE_SIZE * num_images * NUM_CHANNELS)\n",
    "        data = np.frombuffer(buf, dtype=np.uint8).astype(np.float32)\n",
    "        data = (data - (PIXEL_DEPTH / 2.0)) / PIXEL_DEPTH\n",
    "        data = data.reshape(num_images, NUM_CHANNELS, IMAGE_SIZE, IMAGE_SIZE)\n",
    "        return data\n",
    "\n",
    "def extract_labels(filename, num_images):\n",
    "    \"\"\"将label的数据文件解压缩，并将label读成64位的整数\"\"\"\n",
    "    print('Extracting', filename)\n",
    "    with gzip.open(filename) as bytestream:\n",
    "        bytestream.read(8)\n",
    "        buf = bytestream.read(1 * num_images)\n",
    "        labels = np.frombuffer(buf, dtype=np.uint8).astype(np.int64)\n",
    "    return labels\n",
    "\n",
    "# 将数据解压缩并存储到数组中，60000张图片，60000个label，测试集中有10000张图片\n",
    "train_data = extract_data(train_data_filename, 60000)\n",
    "train_labels = extract_labels(train_labels_filename, 60000)\n",
    "test_data = extract_data(test_data_filename, 10000)\n",
    "test_labels = extract_labels(test_labels_filename, 10000)\n",
    "\n",
    "# 将一部分图片（VALIDATION_SIZE=5000张）定为校验数据集\n",
    "validation_data = train_data[:VALIDATION_SIZE, ...]\n",
    "validation_labels = train_labels[:VALIDATION_SIZE]\n",
    "train_data = train_data[VALIDATION_SIZE:, ...]\n",
    "train_labels = train_labels[VALIDATION_SIZE:]\n",
    "num_epochs = NUM_EPOCHS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f94057232b0>"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAP8AAAD8CAYAAAC4nHJkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAADXZJREFUeJzt3XuMXPV5xvHnsVmvi22InaRbF5wYHENDqDDtykkFjVJxqeNSmeQPFKcljoowSkPUSFFU5KoKf1SVWzUg1KZUTrBiR5SkUqC4jVtCrKgUQgwLMVdDuNgEu8aG2iomCb6s3/6xB7TgnTPrOWfmzPJ+P9JqZs57Lq+O/PjMzG9mfo4IAchnWtMNAGgG4QeSIvxAUoQfSIrwA0kRfiApwg8kRfiBpAg/kNRJvTzYDA/GTM3q5SGBVF7Xz3U4Dnky61YKv+1lkm6SNF3SNyJibdn6MzVLH/ZFVQ4JoMTW2DLpdTt+2m97uqSvSfq4pHMkrbR9Tqf7A9BbVV7zL5X0bEQ8HxGHJX1b0op62gLQbVXCf5qkF8c93lUsewvbq22P2B45okMVDgegTl1/tz8i1kXEcEQMD2iw24cDMElVwr9b0oJxj08vlgGYAqqE/0FJi22fYXuGpE9J2lRPWwC6reOhvog4avtaSXdpbKhvfUQ8UVtnALqq0jh/RGyWtLmmXgD0EB/vBZIi/EBShB9IivADSRF+ICnCDyRF+IGkCD+QFOEHkiL8QFKEH0iK8ANJEX4gKcIPJEX4gaQIP5AU4QeSIvxAUoQfSIrwA0kRfiApwg8kRfiBpAg/kBThB5Ii/EBShB9IivADSRF+IKlKs/Ta3inpoKRRSUcjYriOpgB0X6XwF34vIl6pYT8Aeoin/UBSVcMfkr5v+yHbq+toCEBvVH3af2FE7Lb9q5Lutv1URNwzfoXiP4XVkjRTJ1c8HIC6VLryR8Tu4nafpDskLZ1gnXURMRwRwwMarHI4ADXqOPy2Z9me88Z9SZdKeryuxgB0V5Wn/UOS7rD9xn7+OSL+s5auAHRdx+GPiOclnVdjLwB6iKE+ICnCDyRF+IGkCD+QFOEHkiL8QFJ1fKsPbUw/+wOl9V+eMbdHnRxv/28MlNbnPXWk0v5fvPJoy9qPP/oPpdte8KPPldYPH5xRWv/gdTta1kZf+d/SbTPgyg8kRfiBpAg/kBThB5Ii/EBShB9IivADSTHOX/BJ5afixS8f9yNFb7rqj8p/xuDCWbeV1pcOlo+1T2VHYrRl7cCx8m2f/t2NlY595ow/aVlb/BnG+bnyA0kRfiApwg8kRfiBpAg/kBThB5Ii/EBSjPMXysbxJemJL/xjx/s+MFr+nfg/3nlJx/uWpK07F7aszb6vfIq0mZftLa0vOrV8PPy+pxeV1k//t9b/xGbf/WTptk/deHZpfcfyb5TWTz31F6X17LjyA0kRfiApwg8kRfiBpAg/kBThB5Ii/EBSbcf5ba+XdJmkfRFxbrFsnqTvSFooaaekKyLiQPfa7L73bS5v/7zX/7Rlbc7PWn9nXZJO2V6+79Enf1pab+dMbet846+Vl19us/lZeqjjQ3tu+XwFK3/7gY73LUkDtzc3H8JUMJkr/zclLXvbsuskbYmIxZK2FI8BTCFtwx8R90ja/7bFKyRtKO5vkHR5zX0B6LJOX/MPRcSe4v5LkoZq6gdAj1R+wy8iQlK0qttebXvE9sgRHap6OAA16TT8e23Pl6Tidl+rFSNiXUQMR8TwgAY7PByAunUa/k2SVhX3V0m6s552APRK2/Dbvk3S/ZLOtr3L9lWS1kq6xPYzki4uHgOYQtqO80fEyhali2rupVHHHtleWv+1Rzrfd/mnABJ797tKy3899MPS+p6jr5XWT33ulyfcUiZ8wg9IivADSRF+ICnCDyRF+IGkCD+QFD/dja6aNmdOy9qBv6927Vnxl18urc+99/5K+3+n48oPJEX4gaQIP5AU4QeSIvxAUoQfSIrwA0kxzo+u+r8/+FDL2v3n/VOlfb93y89K60cr7f2djys/kBThB5Ii/EBShB9IivADSRF+ICnCDyTFOD+66vV3ueNtP3Dr50rri/6n2hTe2XHlB5Ii/EBShB9IivADSRF+ICnCDyRF+IGk2o7z214v6TJJ+yLi3GLZ9ZKulvRysdqaiNjcrSbRv6bNnFlaX3bNfS1r2w4dKt327Bt2lNaPHmPy8yomc+X/pqRlEyy/MSKWFH8EH5hi2oY/Iu6RtL8HvQDooSqv+a+1/ajt9bbn1tYRgJ7oNPw3S1okaYmkPZK+2mpF26ttj9geOaLy13gAeqej8EfE3ogYjYhjkr4uaWnJuusiYjgihgc02GmfAGrWUfhtzx/38BOSHq+nHQC9MpmhvtskfUzSe2zvkvQVSR+zvURSSNop6Zou9gigC9qGPyJWTrD4li70gilox5rzS+v/MXRzy9rvPPLp0m1P2fNcRz1hcviEH5AU4QeSIvxAUoQfSIrwA0kRfiApfrob5aZNLy1funyktD4ax1rWZq89paOWUA+u/EBShB9IivADSRF+ICnCDyRF+IGkCD+QFOP8KPXc37T8kSZJ0l2/3voru5L0yWd/v2Vt2n/9pKOeUA+u/EBShB9IivADSRF+ICnCDyRF+IGkCD+QFOP8KDVz0auVtv/JUwtb1s56c4Z3NIErP5AU4QeSIvxAUoQfSIrwA0kRfiApwg8k1Xac3/YCSRslDUkKSesi4ibb8yR9R9JCSTslXRERB7rXKrrBAzNK63/1m3eW1n9x7HBpfcH3fMI9oTcmc+U/KulLEXGOpI9I+rztcyRdJ2lLRCyWtKV4DGCKaBv+iNgTEQ8X9w9K2i7pNEkrJG0oVtsg6fJuNQmgfif0mt/2QknnS9oqaSgi9hSllzT2sgDAFDHp8NueLem7kr4YEW/5wHdEhMbeD5hou9W2R2yPHNGhSs0CqM+kwm97QGPBvzUibi8W77U9v6jPl7Rvom0jYl1EDEfE8IAG6+gZQA3aht+2Jd0iaXtE3DCutEnSquL+KknlbwsD6CuT+UrvBZKulPSY7W3FsjWS1kr6F9tXSXpB0hXdaRHd9PM/PL+0fvmsB0rrn3nh4tL6r9xZvj2a0zb8EXGvpFaDtRfV2w6AXuETfkBShB9IivADSRF+ICnCDyRF+IGk+Onu5C7+yn9X2n7ke+eW1hfoR5X2j+7hyg8kRfiBpAg/kBThB5Ii/EBShB9IivADSTHO/w437eSTS+vzTqr2a+vvu+tgaX3C33ZDX+DKDyRF+IGkCD+QFOEHkiL8QFKEH0iK8ANJMc7/Dnf4Ix8srX9hbrXv2+//0OzS+twHK+0eXcSVH0iK8ANJEX4gKcIPJEX4gaQIP5AU4QeSajvOb3uBpI2ShjT29ex1EXGT7eslXS3p5WLVNRGxuVuNojM7PlvtG/Vn/PvVpfWzNj5Qaf9ozmQ+5HNU0pci4mHbcyQ9ZPvuonZjRPxd99oD0C1twx8ReyTtKe4ftL1d0mndbgxAd53Qa37bCyWdL2lrseha24/aXm97bottVtsesT1yRIcqNQugPpMOv+3Zkr4r6YsR8aqkmyUtkrREY88MvjrRdhGxLiKGI2J4QIM1tAygDpMKv+0BjQX/1oi4XZIiYm9EjEbEMUlfl7S0e20CqFvb8Nu2pFskbY+IG8Ytnz9utU9Ierz+9gB0y2Te7b9A0pWSHrO9rVi2RtJK20s0Nvy3U9I1XekQlQw+P7O0PhrHSuvv/9c2Bzg2eoIdoV9M5t3+eyV5ghJj+sAUxif8gKQIP5AU4QeSIvxAUoQfSIrwA0k5oneTKJ/iefFhX9Sz4wHZbI0tejX2TzQ0fxyu/EBShB9IivADSRF+ICnCDyRF+IGkCD+QVE/H+W2/LOmFcYveI+mVnjVwYvq1t37tS6K3TtXZ2/sj4r2TWbGn4T/u4PZIRAw31kCJfu2tX/uS6K1TTfXG034gKcIPJNV0+Nc1fPwy/dpbv/Yl0VunGumt0df8AJrT9JUfQEMaCb/tZbaftv2s7eua6KEV2zttP2Z7m+2RhntZb3uf7cfHLZtn+27bzxS3E06T1lBv19veXZy7bbaXN9TbAts/tP2k7Sds/1mxvNFzV9JXI+et50/7bU+X9FNJl0jaJelBSSsj4smeNtKC7Z2ShiOi8TFh2x+V9JqkjRFxbrHsbyXtj4i1xX+ccyPiz/ukt+slvdb0zM3FhDLzx88sLelySZ9Vg+eupK8r1MB5a+LKv1TSsxHxfEQclvRtSSsa6KPvRcQ9kva/bfEKSRuK+xs09o+n51r01hciYk9EPFzcPyjpjZmlGz13JX01oonwnybpxXGPd6m/pvwOSd+3/ZDt1U03M4GhYtp0SXpJ0lCTzUyg7czNvfS2maX75tx1MuN13XjD73gXRsRvSfq4pM8XT2/7Uoy9Zuun4ZpJzdzcKxPMLP2mJs9dpzNe162J8O+WtGDc49OLZX0hInYXt/sk3aH+m3147xuTpBa3+xru5039NHPzRDNLqw/OXT/NeN1E+B+UtNj2GbZnSPqUpE0N9HEc27OKN2Jke5akS9V/sw9vkrSquL9K0p0N9vIW/TJzc6uZpdXwueu7Ga8joud/kpZr7B3/5yT9RRM9tOjrTEmPFH9PNN2bpNs09jTwiMbeG7lK0rslbZH0jKQfSJrXR719S9Jjkh7VWNDmN9TbhRp7Sv+opG3F3/Kmz11JX42cNz7hByTFG35AUoQfSIrwA0kRfiApwg8kRfiBpAg/kBThB5L6fxv+DTMwdoCNAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9405350518>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#随便从数据集中读入一张图片，并绘制出来\n",
    "idx = 100\n",
    "muteimg = train_data[idx, 0, :, :]\n",
    "plt.imshow(muteimg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义关键函数\n",
    "# 我们在训练中用了一个Tensorflow图，在评价的过程中，我们拷贝了这个图\n",
    "def error_rate(predictions, labels):\n",
    "    \"\"\"计算预测错误率的函数，其中predictions是模型给出的一组预测结果，labels是数据之中的正确答案\"\"\"\n",
    "    predictions = np.argmax(predictions, 1)\n",
    "    return 100.0 - (\n",
    "      100.0 *\n",
    "      np.sum( predictions == labels) /\n",
    "      predictions.shape[0])\n",
    "\n",
    "def eval_in_batches(data, net):\n",
    "    \"\"\"计算得到预测精度，运行对所有的数据集中的小撮数据进行.\"\"\"\n",
    "    size = data.shape[0]\n",
    "    if size < BATCH_SIZE:\n",
    "        raise ValueError(\"batch size for evals larger than dataset: %d\" % size)\n",
    "    predictions = np.ndarray(shape=(size, NUM_LABELS), dtype=np.float32)\n",
    "    \n",
    "    #一个小撮一个小撮地进行预测的计算\n",
    "    for begin in range(0, size, BATCH_SIZE):\n",
    "        end = begin + BATCH_SIZE\n",
    "        if end <= size:\n",
    "            inputs = data[begin:end]\n",
    "            inputs = torch.from_numpy(inputs)\n",
    "            outputs = net(inputs)\n",
    "            predictions[begin:end, :] = outputs.data.numpy()\n",
    "        else:\n",
    "            inputs = data[-BATCH_SIZE:]\n",
    "            inputs = torch.from_numpy(inputs)\n",
    "            outputs = net(inputs)\n",
    "            \n",
    "            batch_predictions = outputs.data.numpy()\n",
    "            predictions[begin:, :] = batch_predictions[begin - size:, :]\n",
    "    return predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized!\n",
      "17187\n",
      "第 0 (epoch 0.00) 步\n",
      "训练测试率: 89.1%\n",
      "校验集测试率: 90.7%\n",
      "第 100 (epoch 0.12) 步\n",
      "训练测试率: 85.9%\n",
      "校验集测试率: 86.6%\n",
      "第 200 (epoch 0.23) 步\n",
      "训练测试率: 89.1%\n",
      "校验集测试率: 83.0%\n",
      "第 300 (epoch 0.35) 步\n",
      "训练测试率: 84.4%\n",
      "校验集测试率: 76.7%\n",
      "第 400 (epoch 0.47) 步\n",
      "训练测试率: 81.2%\n",
      "校验集测试率: 70.0%\n",
      "第 500 (epoch 0.58) 步\n",
      "训练测试率: 60.9%\n",
      "校验集测试率: 62.3%\n",
      "第 600 (epoch 0.70) 步\n",
      "训练测试率: 56.2%\n",
      "校验集测试率: 56.5%\n",
      "第 700 (epoch 0.81) 步\n",
      "训练测试率: 51.6%\n",
      "校验集测试率: 46.6%\n",
      "第 800 (epoch 0.93) 步\n",
      "训练测试率: 45.3%\n",
      "校验集测试率: 33.5%\n",
      "第 900 (epoch 1.05) 步\n",
      "训练测试率: 28.1%\n",
      "校验集测试率: 27.3%\n",
      "第 1000 (epoch 1.16) 步\n",
      "训练测试率: 35.9%\n",
      "校验集测试率: 22.9%\n",
      "第 1100 (epoch 1.28) 步\n",
      "训练测试率: 17.2%\n",
      "校验集测试率: 20.4%\n",
      "第 1200 (epoch 1.40) 步\n",
      "训练测试率: 15.6%\n",
      "校验集测试率: 18.5%\n",
      "第 1300 (epoch 1.51) 步\n",
      "训练测试率: 9.4%\n",
      "校验集测试率: 17.2%\n",
      "第 1400 (epoch 1.63) 步\n",
      "训练测试率: 12.5%\n",
      "校验集测试率: 15.3%\n",
      "第 1500 (epoch 1.75) 步\n",
      "训练测试率: 17.2%\n",
      "校验集测试率: 14.4%\n",
      "第 1600 (epoch 1.86) 步\n",
      "训练测试率: 12.5%\n",
      "校验集测试率: 14.1%\n",
      "第 1700 (epoch 1.98) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 12.7%\n",
      "第 1800 (epoch 2.09) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 12.2%\n",
      "第 1900 (epoch 2.21) 步\n",
      "训练测试率: 17.2%\n",
      "校验集测试率: 11.3%\n",
      "第 2000 (epoch 2.33) 步\n",
      "训练测试率: 7.8%\n",
      "校验集测试率: 10.2%\n",
      "第 2100 (epoch 2.44) 步\n",
      "训练测试率: 14.1%\n",
      "校验集测试率: 9.7%\n",
      "第 2200 (epoch 2.56) 步\n",
      "训练测试率: 17.2%\n",
      "校验集测试率: 9.1%\n",
      "第 2300 (epoch 2.68) 步\n",
      "训练测试率: 15.6%\n",
      "校验集测试率: 9.2%\n",
      "第 2400 (epoch 2.79) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 8.8%\n",
      "第 2500 (epoch 2.91) 步\n",
      "训练测试率: 7.8%\n",
      "校验集测试率: 8.0%\n",
      "第 2600 (epoch 3.03) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 7.8%\n",
      "第 2700 (epoch 3.14) 步\n",
      "训练测试率: 12.5%\n",
      "校验集测试率: 7.8%\n",
      "第 2800 (epoch 3.26) 步\n",
      "训练测试率: 9.4%\n",
      "校验集测试率: 7.3%\n",
      "第 2900 (epoch 3.37) 步\n",
      "训练测试率: 12.5%\n",
      "校验集测试率: 7.3%\n",
      "第 3000 (epoch 3.49) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 6.7%\n",
      "第 3100 (epoch 3.61) 步\n",
      "训练测试率: 9.4%\n",
      "校验集测试率: 6.8%\n",
      "第 3200 (epoch 3.72) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 6.4%\n",
      "第 3300 (epoch 3.84) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 6.2%\n",
      "第 3400 (epoch 3.96) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 6.1%\n",
      "第 3500 (epoch 4.07) 步\n",
      "训练测试率: 7.8%\n",
      "校验集测试率: 5.5%\n",
      "第 3600 (epoch 4.19) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 5.6%\n",
      "第 3700 (epoch 4.31) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 5.7%\n",
      "第 3800 (epoch 4.42) 步\n",
      "训练测试率: 12.5%\n",
      "校验集测试率: 5.6%\n",
      "第 3900 (epoch 4.54) 步\n",
      "训练测试率: 9.4%\n",
      "校验集测试率: 5.8%\n",
      "第 4000 (epoch 4.65) 步\n",
      "训练测试率: 9.4%\n",
      "校验集测试率: 5.1%\n",
      "第 4100 (epoch 4.77) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 5.2%\n",
      "第 4200 (epoch 4.89) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 5.0%\n",
      "第 4300 (epoch 5.00) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 5.2%\n",
      "第 4400 (epoch 5.12) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 4.8%\n",
      "第 4500 (epoch 5.24) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 4.7%\n",
      "第 4600 (epoch 5.35) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 4.7%\n",
      "第 4700 (epoch 5.47) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 4.4%\n",
      "第 4800 (epoch 5.59) 步\n",
      "训练测试率: 9.4%\n",
      "校验集测试率: 4.4%\n",
      "第 4900 (epoch 5.70) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 4.3%\n",
      "第 5000 (epoch 5.82) 步\n",
      "训练测试率: 10.9%\n",
      "校验集测试率: 3.9%\n",
      "第 5100 (epoch 5.93) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 3.9%\n",
      "第 5200 (epoch 6.05) 步\n",
      "训练测试率: 7.8%\n",
      "校验集测试率: 4.5%\n",
      "第 5300 (epoch 6.17) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 4.2%\n",
      "第 5400 (epoch 6.28) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 3.9%\n",
      "第 5500 (epoch 6.40) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 3.9%\n",
      "第 5600 (epoch 6.52) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 3.7%\n",
      "第 5700 (epoch 6.63) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 4.0%\n",
      "第 5800 (epoch 6.75) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 4.0%\n",
      "第 5900 (epoch 6.87) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 3.6%\n",
      "第 6000 (epoch 6.98) 步\n",
      "训练测试率: 7.8%\n",
      "校验集测试率: 3.9%\n",
      "第 6100 (epoch 7.10) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 3.5%\n",
      "第 6200 (epoch 7.21) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 3.9%\n",
      "第 6300 (epoch 7.33) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 3.6%\n",
      "第 6400 (epoch 7.45) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 3.2%\n",
      "第 6500 (epoch 7.56) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 3.5%\n",
      "第 6600 (epoch 7.68) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 3.6%\n",
      "第 6700 (epoch 7.80) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 3.5%\n",
      "第 6800 (epoch 7.91) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 3.5%\n",
      "第 6900 (epoch 8.03) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 3.5%\n",
      "第 7000 (epoch 8.15) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 3.4%\n",
      "第 7100 (epoch 8.26) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 3.4%\n",
      "第 7200 (epoch 8.38) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 3.4%\n",
      "第 7300 (epoch 8.49) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 3.0%\n",
      "第 7400 (epoch 8.61) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 3.4%\n",
      "第 7500 (epoch 8.73) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.9%\n",
      "第 7600 (epoch 8.84) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.9%\n",
      "第 7700 (epoch 8.96) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 3.1%\n",
      "第 7800 (epoch 9.08) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 3.3%\n",
      "第 7900 (epoch 9.19) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.8%\n",
      "第 8000 (epoch 9.31) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 3.0%\n",
      "第 8100 (epoch 9.43) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.9%\n",
      "第 8200 (epoch 9.54) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.9%\n",
      "第 8300 (epoch 9.66) 步\n",
      "训练测试率: 9.4%\n",
      "校验集测试率: 2.8%\n",
      "第 8400 (epoch 9.77) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 3.0%\n",
      "第 8500 (epoch 9.89) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.8%\n",
      "第 8600 (epoch 10.01) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.9%\n",
      "第 8700 (epoch 10.12) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.9%\n",
      "第 8800 (epoch 10.24) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 3.0%\n",
      "第 8900 (epoch 10.36) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.8%\n",
      "第 9000 (epoch 10.47) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.8%\n",
      "第 9100 (epoch 10.59) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.7%\n",
      "第 9200 (epoch 10.71) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.8%\n",
      "第 9300 (epoch 10.82) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.7%\n",
      "第 9400 (epoch 10.94) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.7%\n",
      "第 9500 (epoch 11.05) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 2.8%\n",
      "第 9600 (epoch 11.17) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.7%\n",
      "第 9700 (epoch 11.29) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.7%\n",
      "第 9800 (epoch 11.40) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.8%\n",
      "第 9900 (epoch 11.52) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.6%\n",
      "第 10000 (epoch 11.64) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.4%\n",
      "第 10100 (epoch 11.75) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.6%\n",
      "第 10200 (epoch 11.87) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.5%\n",
      "第 10300 (epoch 11.99) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.6%\n",
      "第 10400 (epoch 12.10) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.9%\n",
      "第 10500 (epoch 12.22) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.6%\n",
      "第 10600 (epoch 12.33) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.4%\n",
      "第 10700 (epoch 12.45) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.4%\n",
      "第 10800 (epoch 12.57) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.2%\n",
      "第 10900 (epoch 12.68) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.4%\n",
      "第 11000 (epoch 12.80) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.6%\n",
      "第 11100 (epoch 12.92) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.5%\n",
      "第 11200 (epoch 13.03) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.5%\n",
      "第 11300 (epoch 13.15) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.7%\n",
      "第 11400 (epoch 13.27) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.4%\n",
      "第 11500 (epoch 13.38) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 2.6%\n",
      "第 11600 (epoch 13.50) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.3%\n",
      "第 11700 (epoch 13.61) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.5%\n",
      "第 11800 (epoch 13.73) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.3%\n",
      "第 11900 (epoch 13.85) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.5%\n",
      "第 12000 (epoch 13.96) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.3%\n",
      "第 12100 (epoch 14.08) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.4%\n",
      "第 12200 (epoch 14.20) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 2.4%\n",
      "第 12300 (epoch 14.31) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.5%\n",
      "第 12400 (epoch 14.43) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.4%\n",
      "第 12500 (epoch 14.55) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.1%\n",
      "第 12600 (epoch 14.66) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.2%\n",
      "第 12700 (epoch 14.78) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.4%\n",
      "第 12800 (epoch 14.89) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.3%\n",
      "第 12900 (epoch 15.01) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.0%\n",
      "第 13000 (epoch 15.13) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.7%\n",
      "第 13100 (epoch 15.24) 步\n",
      "训练测试率: 6.2%\n",
      "校验集测试率: 2.2%\n",
      "第 13200 (epoch 15.36) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.2%\n",
      "第 13300 (epoch 15.48) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.0%\n",
      "第 13400 (epoch 15.59) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.1%\n",
      "第 13500 (epoch 15.71) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.3%\n",
      "第 13600 (epoch 15.83) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.2%\n",
      "第 13700 (epoch 15.94) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.2%\n",
      "第 13800 (epoch 16.06) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.3%\n",
      "第 13900 (epoch 16.17) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.5%\n",
      "第 14000 (epoch 16.29) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.3%\n",
      "第 14100 (epoch 16.41) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.1%\n",
      "第 14200 (epoch 16.52) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.2%\n",
      "第 14300 (epoch 16.64) 步\n",
      "训练测试率: 9.4%\n",
      "校验集测试率: 2.4%\n",
      "第 14400 (epoch 16.76) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 1.8%\n",
      "第 14500 (epoch 16.87) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.1%\n",
      "第 14600 (epoch 16.99) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.4%\n",
      "第 14700 (epoch 17.11) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.3%\n",
      "第 14800 (epoch 17.22) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.1%\n",
      "第 14900 (epoch 17.34) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.0%\n",
      "第 15000 (epoch 17.45) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.1%\n",
      "第 15100 (epoch 17.57) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 2.1%\n",
      "第 15200 (epoch 17.69) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.1%\n",
      "第 15300 (epoch 17.80) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.2%\n",
      "第 15400 (epoch 17.92) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.0%\n",
      "第 15500 (epoch 18.04) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.3%\n",
      "第 15600 (epoch 18.15) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.0%\n",
      "第 15700 (epoch 18.27) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 1.9%\n",
      "第 15800 (epoch 18.39) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.0%\n",
      "第 15900 (epoch 18.50) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.2%\n",
      "第 16000 (epoch 18.62) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.1%\n",
      "第 16100 (epoch 18.73) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 1.9%\n",
      "第 16200 (epoch 18.85) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.0%\n",
      "第 16300 (epoch 18.97) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.1%\n",
      "第 16400 (epoch 19.08) 步\n",
      "训练测试率: 0.0%\n",
      "校验集测试率: 2.2%\n",
      "第 16500 (epoch 19.20) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.0%\n",
      "第 16600 (epoch 19.32) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 1.8%\n",
      "第 16700 (epoch 19.43) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 1.9%\n",
      "第 16800 (epoch 19.55) 步\n",
      "训练测试率: 4.7%\n",
      "校验集测试率: 2.0%\n",
      "第 16900 (epoch 19.67) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 1.9%\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第 17000 (epoch 19.78) 步\n",
      "训练测试率: 1.6%\n",
      "校验集测试率: 1.9%\n",
      "第 17100 (epoch 19.90) 步\n",
      "训练测试率: 3.1%\n",
      "校验集测试率: 2.1%\n",
      "测试误差: 2.2%\n"
     ]
    }
   ],
   "source": [
    "\n",
    "error_rate_rec = []\n",
    "\n",
    "#获得训练集尺寸\n",
    "train_size = train_labels.shape[0]\n",
    "\n",
    "print('Initialized!')\n",
    "\n",
    "net = ConvNet()\n",
    "\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 开始训练循环，一共进行int(num_epochs * train_size) // BATCH_SIZE次\n",
    "print(int(num_epochs * train_size) // BATCH_SIZE)\n",
    "for step in range(int(num_epochs * train_size) // BATCH_SIZE):\n",
    "    # 计算当前应该访问训练集中的哪一部分数据\n",
    "    # Note that we could use better randomization across epochs.\n",
    "    offset = (step * BATCH_SIZE) % (train_size - BATCH_SIZE)\n",
    "    batch_data = train_data[offset:(offset + BATCH_SIZE), ...]\n",
    "    batch_labels = train_labels[offset:(offset + BATCH_SIZE)]\n",
    "    batch_data = torch.from_numpy(batch_data)\n",
    "    batch_labels = torch.from_numpy(batch_labels)\n",
    "    \n",
    "    inputs, labels = batch_data, batch_labels\n",
    "    \n",
    "    \n",
    "    # zero the parameter gradients\n",
    "    optimizer.zero_grad()\n",
    "\n",
    "    # forward + backward + optimize\n",
    "    outputs = net(inputs)\n",
    "    loss = criterion(outputs, labels)\n",
    "    #print(loss)\n",
    "    loss.backward()\n",
    "    optimizer.step()\n",
    "    \n",
    "    if step % EVAL_FREQUENCY == 0:\n",
    "        #每间隔EVAL_FREQUENCY就打印一次预测结果\n",
    "        \n",
    "        print('第 %d (epoch %.2f) 步' %\n",
    "              (step, float(step) * BATCH_SIZE / train_size))\n",
    "        #print('损失函数值: %.3f, 学习率: %.6f' % (l, lr))\n",
    "        predictions = outputs.data.numpy()\n",
    "        #print(predictions.shape)\n",
    "        err_train = error_rate(predictions, labels.data.numpy())\n",
    "        prediction = eval_in_batches(validation_data, net)\n",
    "        err_valid = error_rate(prediction, validation_labels)\n",
    "        print('训练测试率: %.1f%%' % err_train)\n",
    "        print('校验集测试率: %.1f%%' % err_valid)\n",
    "        error_rate_rec.append([err_train,err_valid])\n",
    "        sys.stdout.flush()\n",
    "# 在测试集上实验\n",
    "prediction = eval_in_batches(test_data, net)\n",
    "test_error = error_rate(prediction, test_labels)\n",
    "print('测试误差: %.1f%%' % test_error)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0,0.5,'Error Rate')"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f94050f15f8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(error_rate_rec)\n",
    "plt.xlabel('Batches')\n",
    "plt.ylabel('Error Rate')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.980168269231\n"
     ]
    }
   ],
   "source": [
    "\n",
    "#将测试集喂进去，得到计算结果，看一看预测的准确度\n",
    "right = 0\n",
    "batch_num = len(test_data) // BATCH_SIZE\n",
    "for i in range(batch_num):\n",
    "    inputs = test_data[i * BATCH_SIZE : (i + 1) * BATCH_SIZE]\n",
    "    inputs = torch.from_numpy(inputs)\n",
    "    result = net(inputs)\n",
    "    result = result.data.numpy()\n",
    "    \n",
    "    labels = test_labels[i * BATCH_SIZE : (i + 1) * BATCH_SIZE]\n",
    "    right += np.sum(np.argmax(result, 1) == labels)\n",
    "print(right / float(batch_num * BATCH_SIZE))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
